package com.linzm.leetcode.primary.数组.长度最小的子数组;

import org.junit.Test;

/**
 * @Author zimingl
 * @Date 2022/10/6 17:17
 * @Description: TODO
 */
public class 数组209长度最小的子数组 {
    /**
     * 接下来就开始介绍数组操作中另一个重要的方法：滑动窗口。
     * 所谓滑动窗口，就是不断的调节子序列的起始位置和终止位置，从而得出我们要想的结果。
     * 在暴力解法中，是一个for循环滑动窗口的起始位置，一个for循环为滑动窗口的终止位置，用两个for循环 完成了一个不断搜索区间的过程。
     * 那么滑动窗口如何用一个for循环来完成这个操作呢。
     * 首先要思考 如果用一个for循环，那么应该表示 滑动窗口的起始位置，还是终止位置。
     * 如果只用一个for循环来表示 滑动窗口的起始位置，那么如何遍历剩下的终止位置？
     * 此时难免再次陷入 暴力解法的怪圈。
     * 所以 只用一个for循环，那么这个循环的索引，一定是表示 滑动窗口的终止位置。
     */

    // 滑动窗口
    public int minSubArrayLen(int s, int[] nums) {
        int result = Integer.MAX_VALUE;
        int sum = 0; // 滑动窗口数值之和
        int i = 0; // 滑动窗口起始位置
        int subLength = 0; // 滑动窗口的长度
        for (int j = 0; j < nums.length; j++) {
            sum += nums[j];
            // 注意这里使用while，每次更新 i（起始位置），并不断比较子序列是否符合条件
            while (sum >= s) {
                subLength = (j - i + 1); // 取子序列的长度
                result = result < subLength ? result : subLength;
                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处，不断变更i（子序列的起始位置）
            }
        }
        // 如果result没有被赋值的话，就返回0，说明没有符合条件的子序列
        return result == Integer.MAX_VALUE ? 0 : result;
    }

    private static int minSubArrayLen2(int target, int[] nums) {
        int result = Integer.MAX_VALUE;
        int sum = 0;
        int i = 0;
        for (int j = 0; j < nums.length; j++) {
            sum += nums[i];
            while (target <= sum) {
                int subLength = j - i + 1;
                result = Math.min(result, subLength);
                sum -= nums[i++];
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }

    @Test
    public void test(){
        int target = 7;
        int[] nums = new int[]{2, 3, 1, 2, 4, 3};
        int i = minSubArrayLen(target, nums);
        System.out.println(i);
    }












    public int method(int[] nums, int s){
        int result = Integer.MAX_VALUE;
        int sum = 0;
        int i = 0;
        int subLen;
        for (int j = 0; j < nums.length; j++) {
            sum += nums[j];
            while (sum >= s){
                subLen = j - i + 1;
                result = result < subLen ? result : subLen;
                sum = sum - nums[i++];
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }
}
